import numpy as np

def mergify(*args):                                                                                                           
    """                                                                                                                       
    >>> a = np.array([[1, 4], [6, 10]], dtype=np.float)                                                                       
    >>> b = np.array([[1, 3], [6, 12]], dtype=np.float)                                                                       
    >>> c = np.array([[1, 2], [6, 12], [15, 18]] ,dtype=np.float)                                                             
    >>> d = np.array([[25, 28]] ,dtype=np.float)                                                                              
    >>> mergify(a, b, c, d) #doctest: +NORMALIZE_WHITESPACE                                                                   
    [[1.0, 4.0], [6.0, 12.0], [15.0, 18.0], [25.0, 28.0]]                                                                     
    """                                                                                                                       
    if len(args) < 2: return args[0]                                                                                          
    if isinstance(args[0], (tuple, list)):                                                                                    
        b = np.array(args)                                                                                                    
    else:                                                                                                                     
        b = np.concatenate(args)                                                                                              
    b.sort(axis=0)                                                                                                            
    b = [list(xy) for xy in b]                                                                                                
                                                                                                                              
    l = [b[0]]                                                                                                                
    for xy in b[1:]:                                                                                                          
        if xy[0] <= l[-1][1]:                                                                                                 
            l[-1][1] = xy[1]                                                                                                  
        else:                                                                                                                 
            l.append(xy)                                                                                                      
    return l                     



def merge_feature_inplace(feature):
    """take a simple feature (like the one created by read_gff)
    and merge overlapping exons (e.g. from alternative splicings)

>>> feat = {'chr': 'Chr4',
... 'locations': {'CDS': [(13282379, 13282560), (13282941, 13283127)],
...               'EXON': [(13281946, 13282037),
...                        (13282363, 13282560),
...                        (13282941, 13283411)],
...               'FIVE_PRIME_UTR': [(13281946, 13282037), (13282363, 13282378)],
...               'GENE': [(13281946, 13283411)],
...               'MRNA': [(13281946, 13283411)],
...               'THREE_PRIME_UTR': [(13283128, 13283411)]},
... 'name': 'AT4G26210',
... 'start': 13281946,
... 'stop': 13283411,
... 'strand': 1}

>>> merge_feature_inplace(feat)
>>> from pprint import pprint
>>> pprint(feat)
{'chr': 'Chr4',
 'locations': {'CDS': [(13282379, 13282560), (13282941, 13283127)],
               'EXON': [(13281946, 13282037),
                        (13282363, 13282560),
                        (13282941, 13283411)],
               'FIVE_PRIME_UTR': [(13281946, 13282037), (13282363, 13282378)],
               'GENE': [(13281946, 13283411)],
               'MRNA': [(13281946, 13283411)],
               'THREE_PRIME_UTR': [(13283128, 13283411)]},
 'name': 'AT4G26210',
 'start': 13281946,
 'stop': 13283411,
 'strand': 1}
    """
    for ftype in feature['locations']:
        feature['locations'][ftype] = mergify(feature['locations'][ftype])

        
if __name__ == "__main__":
    import doctest
    doctest.testmod()
